home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Games of Daze
/
Infomagic - Games of Daze (Summer 1995) (Disc 1 of 2).iso
/
x2ftp
/
msdos
/
libs
/
ctask22d
/
tsksub.c
< prev
next >
Wrap
C/C++ Source or Header
|
1992-09-02
|
5KB
|
219 lines
/*
--- Version 2.2 92-09-02 12:42 ---
CTask Subroutines
Public Domain Software written by
Thomas Wagner
Ferrari electronic Gmbh
Beusselstrasse 27
D-1000 Berlin 21
Germany
Note: The find_xxx_name functions were moved to a separate file,
'tskname.c', in version 2.1 for potential code savings.
*/
#include "tsk.h"
#include "tsklocal.h"
/*
tsk_runable
Make a task eligible for running. The task is removed from the
timer queue and enqueued in the eligible queue.
CAUTION: Critical section assumed entered.
*/
void Localfunc tsk_runable (tcbptr task)
{
CHECK_TCBPTR (task, "Task Runable");
task->state = ST_ELIGIBLE;
tsk_deqtimer (&task->timerq.link);
tsk_dequeue (&task->cqueue);
tsk_enqueue (task->qhead = &GLOBDATA eligible_queue, &task->cqueue);
}
/*
tsk_run_pending
Make a task eligible for running, but don't enqueue it in the
eligible queue.
CAUTION: Critical section assumed entered.
*/
void Localfunc tsk_run_pending (tcbptr task)
{
CHECK_TCBPTR (task, "Task Runable");
task->state = ST_ELIGIBLE;
tsk_deqtimer (&task->timerq.link);
tsk_dequeue (&task->cqueue);
}
/*
tsk_runable_all
Make all tasks in a queue eligible for running.
CAUTION: Critical section assumed entered.
*/
void Localfunc tsk_runable_all (queheadptr que)
{
queptr curr;
tcbptr task;
CHECK_QHEAD (que, "Task Runable All: Queue");
for (curr = que->first; !(curr->kind & Q_HEAD); )
{
task = (tcbptr)curr;
CHECK_TCBPTR (task, "Task Runable All: TCB");
curr = curr->next;
task->state = ST_ELIGIBLE;
tsk_deqtimer (&task->timerq.link);
tsk_enqueue (task->qhead = &GLOBDATA eligible_queue, &task->cqueue);
}
tsk_init_qhead (que, que->kind);
}
/*
tsk_wait
put current running task in wait state.
With version 2.2, the wait action was changed to immediately
enqueue the task into the respective queue. In previous versions,
the task was not enqueued, this was done by the scheduler based
on the queue head pointer. Starting with version 2.1, interrupts
are enabled early in the scheduler, before the scheduler gets to
the point where it enqueues the task. This could lead to race
conditions, with tasks being only partially enqueued, or never
dequeued, when "tsk_runable" was called by an interrupt handler
hitting in this interval.
CAUTION: Critical section assumed entered.
*/
void Localfunc tsk_wait (queheadptr que, dword timeout)
{
tcbptr curr;
/*
Note: The following test shouldn't be necessary. However,
if ever an interrupt handler should cause the current task to
be made waiting while the scheduler is active, this would cause
catastrophic effects (also see the notes in tskasm.asm).
Well, no interrupt handler should ever do such a nasty thing, but...
So if the in_sched flag is set, we have to stop everything.
The test is ommitted when we're not running under DOS.
*/
#if (DOS || DEBUG)
if (GLOBDATA in_sched)
tsk_fatal ("Wait while in Scheduler");
#endif
CHECK_QHEAD (que, "Task Wait: Queue");
curr = GLOBDATA current_task;
curr->state = ST_WAITING;
tsk_enqueue (curr->qhead = que, &curr->cqueue);
if (timeout)
{
tsk_enqtimer (&curr->timerq.link, tsk_timeout(timeout));
curr->timerq.flags = 0;
curr->timerq.link.kind = TYP_TIMER;
}
schedule ();
}
#if (TSK_NAMED)
/*
tsk_copy_name
A replacement for strcpy, used for copying names. The C-runtime
strcpy is not used here to keep the kernel model independent.
*/
void Localfunc tsk_copy_name (nameptr elem, byteptr name)
{
byteptr n;
int i;
n = elem->name;
if (name != LNULL)
for (i = 0; i < 8; i++)
if ((*n++ = *name++) == 0)
break;
*n = 0;
}
/*
tsk_add_name
Initialise name-list element and insert it into the name list.
NOTE: no check is made for duplicate names; names are not sorted.
Version 2.1 allows name pointers to be LNULL. Structures with LNULL
name pointers are not added to the list.
*/
void Localfunc tsk_add_name (nameptr elem, byteptr name, byte kind, farptr strucp)
{
CRITICAL;
elem->list.kind = kind;
elem->strucp = strucp;
if (name == LNULL)
{
elem->list.first = LNULL;
elem->name [0] = 0;
return;
}
tsk_copy_name (elem, name);
C_ENTER;
#if (GROUPS)
tsk_putqueue (&GLOBDATA current_task->group->namelist.list, (queptr)&elem->list);
#else
tsk_putqueue (&GLOBDATA name_list.list, (queptr)&elem->list);
#endif
C_LEAVE;
}
/*
tsk_del_name
delete name-element from the name-list.
*/
void Localfunc tsk_del_name (nameptr elem)
{
CRITICAL;
C_ENTER;
tsk_dequeue ((queptr)&elem->list);
C_LEAVE;
}
#endif
/*
tsk_init_qhead
Initializes the head of a queue.
*/
void Localfunc tsk_init_qhead (queheadptr head, byte kind)
{
head->kind = Q_HEAD | kind;
head->first = head->last = (queptr)head;
}